package cn.jasonone.him.util;

import java.util.Collection;
import java.util.Date;
import java.util.UUID;

import com.corundumstudio.socketio.BroadcastOperations;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.jasonone.him.HimConst;
import cn.jasonone.him.exception.NotFoundClientException;
import cn.jasonone.him.exception.NullException;
import cn.jasonone.him.model.HimUserInfo;
import cn.jasonone.him.model.R;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class HimUtil implements HimConst {
	@Setter
	private static SocketIOServer server;

	/**
	 * 根据用户ID获取用户对象
	 * 
	 * @param userId 用户ID
	 * @return 用户对象
	 */
	public static HimUserInfo getUserInfoById(String userId) {
		if (userId != null) {
			Collection<SocketIOClient> clients = server.getAllClients();
			for (SocketIOClient client : clients) {
				HimUserInfo userInfo = getUserInfo(client);
				if (userInfo != null && userId.equals(userInfo.getId())) {
					return userInfo;
				}
			}
		}
		return null;
	}

	/**
	 * 获得当前客户端的用户对象
	 * 
	 * @param client 客户端对象
	 * @return 用户对象
	 */
	public static HimUserInfo getUserInfo(SocketIOClient client) {
		return client.get(SESSION_USER);
	}

	/**
	 * 通用消息发送方法
	 * 
	 * @param groupId   群ID
	 * @param eventName 事件名称
	 * @param data      数据对象
	 */
	public static void send(String groupId, String eventName, Object data) {
		if (StrUtil.isBlank(groupId)) {
			throw new NullException("群ID不能为空");
		}
		BroadcastOperations operations = server.getRoomOperations(groupId);
		if (operations == null) {
			throw new NotFoundClientException("群未找到:{}", groupId);
		}
		operations.sendEvent(eventName, data);
	}

	/**
	 * 通用消息发送方法
	 * 
	 * @param sessionID 接收方用户SessionID
	 * @param eventName 事件名称
	 * @param data      数据对象
	 */
	public static void send(UUID sessionID, String eventName, Object data) {
		if (sessionID == null) {
			throw new NullException("接收方用户SessionID不能为空");
		}
		SocketIOClient client = server.getClient(sessionID);
		if (client == null) {
			throw new NotFoundClientException("接收方客户端对象未找到:{}", sessionID);
		}
		client.sendEvent(eventName, data);
	}

	/**
	 * 发送消息给指定用户
	 * 
	 * @param client  客户端对象
	 * @param friend  接收方用户信息
	 * @param message 消息内容
	 */
	public static void sendFriend(SocketIOClient client, HimUserInfo friend, String message) {
		sendFriend(getUserInfo(client), friend, message);
	}

	/**
	 * 发送消息给指定用户
	 * 
	 * @param user    发送方用户信息
	 * @param friend  接收方用户信息
	 * @param message 消息内容
	 */
	public static void sendFriend(HimUserInfo user, HimUserInfo friend, String message) {
		if (StrUtil.isBlank(friend.getId())) {
			throw new NullException("接收方用户ID不能为空");
		}
		if (StrUtil.isBlank(user.getId())) {
			throw new NullException("发送方用户ID不能为空");
		}
		R r = R.success().createChild("data");
		// 消息来源用户名
		r.addItem("username", user.getUsername());
		// 消息来源用户头像
		r.addItem("avatar", user.getAvatar());
		// 聊天窗口来源ID
		r.addItem("id", user.getId());
		// 聊天窗口来源类型，从发送消息传递的to里面获取
		r.addItem("type", "friend");
		// 消息内容
		r.addItem("content", message);
		// 是否我发送的消息，如果为true，则会显示在右方
		r.addItem("mine", user.getId().equals(friend.getId()));
		// 服务端动态时间戳
		r.addItem("timestamp", new Date().getTime());
		// 发送消息
		log.debug("发送消息[{}]:{}", MESSAGE_FRIEND, JSONUtil.toJsonStr(r.getRoot()));
		send(friend.getSessionId(), MESSAGE_FRIEND, r.getRoot());
	}

	/**
	 * 发送消息到指定群
	 * 
	 * @param client  客户端对象
	 * @param groupId 群ID
	 * @param message 消息内容
	 */
	public static void sendGroup(SocketIOClient client, String groupId, String message) {
		HimUserInfo userInfo = getUserInfo(client);
		sendGroup(userInfo, groupId, message);
	}

	/**
	 * 发送消息到指定群
	 * 
	 * @param user    发送方用户信息
	 * @param groupId 群ID
	 * @param message 消息内容
	 */
	public static void sendGroup(HimUserInfo user, String groupId, String message) {
		if (user == null) {
			throw new NullException("发送方对象不能为空");
		}
		if (user.getSessionId() == null) {
			throw new NullException("发送方用户SessionID不能为空");
		}
		if (StrUtil.isBlank(user.getId())) {
			throw new NullException("发送方用户ID不能为空");
		}
		R r = R.success().createChild("data");
		// 消息来源用户名
		r.addItem("username", user.getUsername());
		// 消息来源用户头像
		r.addItem("avatar", user.getAvatar());
		// 聊天窗口来源ID
		r.addItem("id", groupId);
		// 聊天窗口来源类型，从发送消息传递的to里面获取
		r.addItem("type", "group");
		// 消息内容
		r.addItem("content", message);
		// 发送方用户ID
		r.addItem("mine", user.getId());
		// 服务端动态时间戳
		r.addItem("timestamp", new Date().getTime());
		// 发送消息
		log.debug("发送消息[{}]:{}", MESSAGE_GROUP, JSONUtil.toJsonStr(r.getRoot()));
		send(groupId, MESSAGE_GROUP, r.getRoot());
	}

	/**
	 * 发送系统消息给所有用户
	 * 
	 * @param message 消息内容
	 */
	public static void sendSystem(String message) {
		sendSystem(message, null);
	}

	/**
	 * 发送系统消息给所有用户
	 * 
	 * @param message 提示信息
	 * @param data    数据对象
	 */
	public static void sendSystem(String message, Object data) {
		sendSystem(null, message, data);
	}

	/**
	 * 发送系统消息给指定用户
	 * 
	 * @param user    接收方用户对象信息
	 * @param message 消息内容
	 * @param data    数据对象
	 */
	public static void sendSystem(HimUserInfo user, String message, Object data) {
		R r = R.success();
		r.setMsg(message);
		r.addItem("data", data);
		if (user != null) {
			if (user.getSessionId() == null) {
				throw new NullException("接收方用户SessionID不能为空");
			}
			SocketIOClient client = server.getClient(user.getSessionId());
			if (client == null) {
				throw new NotFoundClientException("接收方客户端对象未找到:{}", user.getSessionId());
			}
			log.debug("发送消息[{}]给[{}]:{}", MESSAGE_SYSTEM, user.getSessionId(), JSONUtil.toJsonStr(r));
			client.sendEvent(MESSAGE_SYSTEM, r);
		} else {
			log.debug("发送消息[{}]:{}", MESSAGE_SYSTEM, JSONUtil.toJsonStr(r));
			BroadcastOperations operations = server.getBroadcastOperations();
			if (operations != null) {
				operations.sendEvent(MESSAGE_SYSTEM, JSONUtil.toJsonStr(r));
			}
		}
	}

	/**
	 * 将当前用户加入群聊
	 * 
	 * @param client  客户端对象
	 * @param groupId 群ID
	 */
	public static void addGroup(SocketIOClient client, String groupId) {
		log.debug("用户[{}]加入群聊:{}", client.getSessionId(), groupId);
		client.joinRoom(groupId);
	}

	/**
	 * 将当前用户移出群聊
	 * 
	 * @param client  客户端对象
	 * @param groupId 群ID
	 */
	public static void removeGroup(SocketIOClient client, String groupId) {
		log.debug("用户[{}]退出群聊:{}", client.getSessionId(), groupId);
		client.leaveRoom(groupId);
	}

}
